"""Definition of the Movie content type
"""

from zope.interface import implements, directlyProvides

from Products.Archetypes import atapi
from Products.ATContentTypes.content import folder
from Products.ATContentTypes.content import schemata

from ComputedAttribute import ComputedAttribute
from Products.CMFCore.permissions import View
from Products.CMFCore.permissions import ModifyPortalContent
from AccessControl import ClassSecurityInfo
from Acquisition import aq_base
from Products.ATContentTypes.configuration import zconf
from Products.validation.config import validation
from Products.validation.validators.SupplValidators import MaxSizeValidator
from Products.validation import V_REQUIRED

validation.register(MaxSizeValidator('checkImageMaxSize',
                                     maxsize=zconf.ATImage.max_file_size))

from polygonstudio.marvin import marvinMessageFactory as _
from polygonstudio.marvin.interfaces import IMovie
from polygonstudio.marvin.browser.marvinview import MarvinView
from polygonstudio.marvin.config import PROJECTNAME

from plone.memoize import ram, instance, view
import re, anyjson, urllib2
from DateTime import DateTime
from time import time
from Products.CMFCore.utils import getToolByName
from Products.Archetypes.utils import shasattr
import transaction
from zope.component import getUtility
from Products.CMFCore.interfaces import IPropertiesTool
from Products.CMFPlone.utils import safe_unicode
from Products.Archetypes.public import DisplayList

import logging
logger = logging.getLogger('movie.py')

TYPE = DisplayList((
    ('dvd', 'DVD'),
    ('bd', 'Blu-Ray Disc'),
    ('svcd', 'SVCD'),
    ('hd', 'HD Movie'),
))

MovieSchema = folder.ATFolderSchema.copy() + atapi.Schema((

    # -*- Your Archetypes field definitions here ... -*-

    atapi.StringField(
        'tmdbId',
        storage=atapi.AnnotationStorage(),
        widget=atapi.StringWidget(
            label=_(u"TMDb.org ID"),
            description=_(u"Field description"),
        ),
    ),

   atapi.StringField(
        'type',
        storage=atapi.AnnotationStorage(),
        vocabulary=TYPE,
        widget=atapi.SelectionWidget(
            label=_(u"Type"),
            description=_(u""),
        ),
    ),

    atapi.ImageField(
        'image',
        storage=atapi.AnnotationStorage(),
        swallowResizeExceptions = zconf.swallowImageResizeExceptions.enable,
        pil_quality = zconf.pil_config.quality,
        pil_resize_algo = zconf.pil_config.resize_algo,
        max_size = zconf.ATImage.max_image_dimension,
        sizes= {'preview' : (400, 400),
                'thumb'   : (128, 128),
                'icon'    :  (32, 32),
               },
        widget=atapi.ImageWidget(
            label=_(u"Movie Poster"),
            description=_(u"Please upload a movie poster"),
            show_content_type = False,
        ),
        languageIndependent= True,
        validators=(('isNonEmptyFile'),
                    ('checkImageMaxSize', V_REQUIRED)),
    ),


))

# Set storage on fields copied from ATFolderSchema, making sure
# they work well with the python bridge properties.

MovieSchema['title'].storage = atapi.AnnotationStorage()
MovieSchema['description'].storage = atapi.AnnotationStorage()

MovieSchema['title'].required = 0
MovieSchema['title'].widget.visible = {"edit": "invisible", "view": "visible"}

MovieSchema['description'].required = 0
MovieSchema['description'].widget.visible = {"edit": "invisible", "view": "visible"}

schemata.finalizeATCTSchema(
    MovieSchema,
    folderish=True,
    moveDiscussion=False
)

class Movie(folder.ATFolder):
    """A contenttype for movie information"""
    implements(IMovie)
    security       = ClassSecurityInfo()

    meta_type = "Movie"
    schema = MovieSchema

    title = atapi.ATFieldProperty('title')
    description = atapi.ATFieldProperty('description')
    
    # -*- Your ATSchema to Python Property Bridges Here ... -*-
    tmdbId = atapi.ATFieldProperty('tmdbId')

    image = atapi.ATFieldProperty('image')

    security.declareProtected(View, 'get_size')
    def get_size(self):
        """ZMI / Plone get size method

        BBB: ImageField.get_size() returns the size of the original image + all
        scales but we want only the size of the original image.
        """
        img = self.getImage()
        if not getattr(aq_base(img), 'get_size', False):
            return 0
        return img.get_size()

    security.declareProtected(View, 'getWidth')
    def getWidth(self, scale=None):
        return self.getSize(scale)[0]

    security.declareProtected(View, 'getHeight')
    def getHeight(self, scale=None):
        return self.getSize(scale)[1]

    width = ComputedAttribute(getWidth, 1)
    height = ComputedAttribute(getHeight, 1)

    security.declarePrivate('cmf_edit')
    def cmf_edit(self, precondition='', file=None, title=None):
        if file is not None:
            self.setImage(file)
        if title is not None:
            self.setTitle(title)
        self.reindexObject()

    def __bobo_traverse__(self, REQUEST, name):
        """Transparent access to image scales
        """
        if name.startswith('image'):
            field = self.getField('image')
            image = None
            if name == 'image':
                image = field.getScale(self)
            else:
                scalename = name[len('image_'):]
                if scalename in field.getAvailableSizes(self):
                    image = field.getScale(self, scale=scalename)
            if image is not None and not isinstance(image, basestring):
                # image might be None or '' for empty images
                return image

        return folder.ATFolder.__bobo_traverse__(self, REQUEST, name)

    security.declareProtected(View, 'tag')
    def tag(self, **kwargs):
        """Generate image tag using the api of the ImageField
        """
        return self.getField('image').tag(self, **kwargs)


    security.declarePrivate('_renameAfterCreation')
    def _renameAfterCreation(self, check_auto_id=False):
        """
        Renames an object like its normalized title.
        """
        plone_tool = getToolByName(self, 'plone_utils', None)

        if plone_tool is None or not shasattr(plone_tool, 'normalizeString'):
            # Plone tool is not available or too old
            # XXX log?
            return None

        old_id = self.getId()
        if check_auto_id and not self._isIDAutoGenerated(old_id):
            # No auto generated id
            return False

        new_id = self.getTmdbId() + '-' + self.getMovieInfos()['title']
        new_id = plone_tool.normalizeString(new_id)

        if new_id is None:
            return False

        invalid_id = True
        check_id = getattr(self, 'check_id', None)
        if check_id is not None:
            invalid_id = check_id(new_id, required=1)

        # If check_id told us no, or if it was not found, make sure we have an
        # id unique in the parent folder.
        if invalid_id:
            unique_id = self._findUniqueId(new_id)
            if unique_id is not None:
                if check_id is None or check_id(new_id, required=1):
                    new_id = unique_id
                    invalid_id = False

        if not invalid_id:
            # Can't rename without a subtransaction commit when using
            # portal_factory!
            transaction.savepoint(optimistic=True)
            self.setId(new_id)
            return new_id

        return False

    security.declarePrivate('at_post_create_script') 
    def at_post_create_script(self): 
        """ 
        """
        movie =  self.getMovieInfos() 
        title = movie['title']
        description = movie['description']
        self.setTitle(title)
        self.setDescription(description)
        self.reindexObject() 

    def _cachekey(method, self):
        return self.tmdbId

    @ram.cache(_cachekey)
    def getMovieInfos(self):
        """
        get full movie info from imdb url
        """
        pprop = getUtility(IPropertiesTool)
        self.polygonstudio_marvin_props = getattr(pprop, 'polygonstudio_marvin_properties', None)
        self.portal_props = getattr(pprop, 'portal_properties', None)
        self.encoding = self.portal_props.site_properties.default_charset

        a = DateTime()
        result = {}
        url = 'http://api.themoviedb.org/2.1/Movie.getInfo/%s/json/%s/%s' % (self.polygonstudio_marvin_props.tmdbLanguage,
                                                                             self.polygonstudio_marvin_props.tmdbAPIKey,
                                                                             self.tmdbId)
        logger.info(str(url))
        request = urllib2.Request(url)
        response = urllib2.urlopen(request)
        b = DateTime()
        diff = b.millis() - a.millis()
        logger.info('TMDB.org Webservice Response Time for getMovieInfos(): '+ str(diff) )
        #logger.info('response: ' + response.read())
        #response = response.read()

        #if response == '["Nothing found."]':
        #    logger.info('quit')
        #    return False

        response = anyjson.deserialize(response.read())[0]
        #logger.info('no: ' + response)
        if response == "Nothing found.":
            logger.info('Nothing found.')
            return False

        if response.get('translated'):
            #logger.info('Translated Title: ' + str(response['name']))
            result['title'] = response['name']
        else:
            #logger.info('No translated title')
            result['title'] = response['original_name']
      
        if response.get('overview'):
            #logger.info('Overview: ' + str(response['overview'].encode(self.encoding)))
            result['description'] = safe_unicode(response['overview'])

        return result

atapi.registerType(Movie, PROJECTNAME)
